Realtime API design guide
New to the subject of realtime APIs? This article is the place to start! We’ll discuss the most common design approaches and their pros/cons, as well as link to the documentation of 16 public realtime APIs that you can use for inspiration.
Unlike request/response APIs, which almost always use conventional HTTP exchanges, realtime APIs may use HTTP in unconventional ways or even use non-HTTP protocols. There are four common realtime API mechanisms:
- HTTP streaming: Client makes an HTTP request, and the server trickles out a response of indefinite length. HTTP streaming is performant and easy to consume.
- HTTP long-polling: Client makes an HTTP request, and the server waits before responding with a complete response. HTTP long-polling is fault-tolerant and blends well with request/response endpoints.
- WebSockets: Client connects to server and establishes a bidirectional message pipe.
- Webhooks: Service makes an HTTP request to a receiver URL. Webhooks are easy to implement, though the receiver must run an HTTP server.
The best APIs offer simple connectivity. This means your API should make use of the above mechanisms in a way that is easy for your consumers to understand and that allows access via generic tools (e.g. curl
). Some “APIs” use complex or underdocumented connectivity protocols, but this is not recommended.
Below, we’ll discuss each realtime mechanism in-depth.
HTTP streaming
HTTP streaming provides a long-lived connection for instant and continuous data push. You get the familiarity of HTTP with the performance of WebSockets.
Examples: Twitter, DataSift, Superfeedr, Gitter
How it works: A client makes a request to an HTTP endpoint in the usual way (along with possibly authentication information, again in the usual way), and the server replies with a response of indefinite length. For HTTP/1.1, this means Transfer-Encoding: chunked
. Response data often comes in two flavors: newline-delimited strings (usually JSON, but not always) or Server-Sent Events. The former is slightly easier for typical application developers to parse, while the latter enables browsers to consume the stream using EventSource
.
When to use it: HTTP streaming is a great for pushing data frequently (more than once per minute) to the same receiver.
Caveats: If the client needs to be able to rapidly change what it is listening to, this will require adding (or recreating) HTTP streaming connections. Consider WebSockets in this case.
HTTP long-polling
HTTP long-polling provides a long-lived connection for instant data push. It is the easiest mechanism to consume and also the easiest to make reliable.
Examples: Dropbox, Amazon SQS, Livefyre, Consul
How it works: A client makes a request to an HTTP endpoint in the usual way, with the intention of requesting data it has not yet received. If there is no new data available, then the server holds the request open until data becomes available to respond with. If enough time passes without new data becoming available, then the server sends a timeout response. The length of time the server waits may be specified by the client (for example, via a header or query parameter), or the server may use a fixed default. After receiving a response (whether new data or timeout), the transaction is complete. The client may create a new request to listen for further data.
When to use it: HTTP long-polling is great for making reliable APIs, because sync and listen actions can be combined into the same request. If you already have a polling API that clients can use to sync with the server, it’s easy to augment it into a long-polling API while retaining the same semantics. Since long-polling uses request/response interactions, you can even make it RESTful. Short timeouts make network resilience effortless; if a user’s IP address changes due to roaming between wireless access points or tethering, a good long-polling API will weather the storm.
Caveats: Uses more bandwidth than other mechanisms, particularly if you push data to the same receiver more frequently than the request timeout. If you push extremely often (faster than the round trip latency with the client), then expect a batching effect as well.
WebSockets
A WebSocket provides a long-lived connection for exchanging messages between client and server. Messages may flow in either direction for full-duplex communication. Commandline access is possible with wscat
.
Examples: Blockchain, Coinbase, CBIX, Slack
How it works: A client creates a WebSocket connection to a server, using a WebSocket client library. WebSocket libraries are generally available in every language, and of course browsers support it natively using the WebSocket JavaScript object. The connection negotiation uses an HTTP-like exchange, and a successful negotiation is indicated with status code 101. After the negotiation response is sent, the connection remains open to be used for exchanging message frames in either binary or unicode string format. Peers may also exchange close frames to perform a clean close.
When to use it: Popular among Bitcoin APIs, WebSockets are great for allowing low-latency tuning of the data to be sent over it (as opposed to HTTP streaming, where a new TCP connection would be needed for each change). Browsers also don’t enforce a connection limit on WebSockets, so they work better for browser apps that use many tabs and communicate with the same domain.
Caveats: While WebSockets as a technology is not exactly new, it is still relatively new in the context of APIs. Also, there is no standard support in WebSocket messages for the things we love about HTTP such as status codes and headers. WebSockets are a great addition to a realtime API, but they should probably not be the sole access mechanism.
Webhooks
Webhooks are a simple way of sending data between servers. No long-lived connections are needed. The sender makes an HTTP request to the receiver when there is data to push.
Examples: GitHub, Facebook, Stripe, Zapier
How it works: Just make an HTTP request to a callback URL. It’s that easy! The request method is usually POST
. Some APIs require the callback URLs to be configured manually using a user interface. Others offer programmatic registration. See REST Hooks for some nice guidelines on how to add programmatic registration to a RESTful API. You may also consider PubSubHubbub if you are sending feed updates.
When to use it: Webhooks are great for pushing data to other servers. Also, if you’re not sure who will consume your realtime API, Webhooks are a good place to start because the barrier to entry is low. You can easily make HTTP requests directly from your server code, without setting up any new components or changing programming languages.
Caveats: Browsers and other client applications cannot receive Webhooks directly, so if you want a client application to support live updates then you’ll need to use one of the other mechanisms. Webhooks are also harder to test (compared to just running curl
or wscat
), but tools like ngrok, WebhookInbox, and RequestBin can help with this.
Seriously, though, which one do I use?
Use any or all, whichever makes most sense for your API. If you could only pick one mechanism, then we’d recommend HTTP streaming, as it’s a good mix of simplicity and compatibility.
It is not uncommon for APIs to offer more than one realtime access mechanism, though. For example, Dropbox supports both HTTP long-polling and Webhooks.
Conclusion
Just as with request/response APIs, the best realtime APIs are easy to understand and easy to consume. We hope you find this guide handy as your API enters the brave new world of realtime!
Recent posts
-
We've been acquired by Fastly
-
A cloud-native platform for push APIs
-
Vercel and WebSockets
-
Rewriting Pushpin's connection manager in Rust
-
Let's Encrypt for custom domains